<!DOCTYPE html>
<html>
<head>
  <title>Mass-Spring System</title>
  <style>
    body {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      background-color: #f0f0f0;
    }
    canvas {
      border: 1px solid #ccc;
      background-color: #fff;
    }
  </style>
</head>
<body>
  <canvas id="physicsCanvas" width="600" height="300"></canvas>
  <script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // Drawing parameters
    const baseX = 70;
    const baseY = 140;
    const springLength = 360;
    const massRadius = 8;
    const massX = baseX + springLength;
    const massY = baseY;
    const velocityVectorLength = 80;
    const angleRad = -Math.PI / 4; // -45 degrees for canvas coordinates

    // General style settings
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';
    ctx.lineWidth = 2;

    /**
     * Helper function to draw an arrow from (fromX, fromY) to (toX, toY).
     */
    function drawArrow(ctx, fromX, fromY, toX, toY) {
      const headLength = 12;
      const dx = toX - fromX;
      const dy = toY - fromY;
      const angle = Math.atan2(dy, dx);

      ctx.beginPath();
      ctx.moveTo(fromX, fromY);
      ctx.lineTo(toX, toY);
      ctx.lineTo(toX - headLength * Math.cos(angle - Math.PI / 6), toY - headLength * Math.sin(angle - Math.PI / 6));
      ctx.moveTo(toX, toY);
      ctx.lineTo(toX - headLength * Math.cos(angle + Math.PI / 6), toY - headLength * Math.sin(angle + Math.PI / 6));
      ctx.stroke();
    }

    /**
     * Helper function to draw a spring.
     */
    function drawSpring(ctx, x, y, length, coils, radius) {
        ctx.beginPath();
        const leadLength = 15;
        const coilSectionLength = length - 2 * leadLength;
        const loopWidth = coilSectionLength / coils;

        ctx.moveTo(x, y);
        ctx.lineTo(x + leadLength, y);

        let currentX = x + leadLength;
        for (let i = 0; i < coils; i++) {
            ctx.arcTo(currentX + loopWidth / 2, y - radius * 1.8, currentX + loopWidth, y, radius);
        }
        
        ctx.lineTo(x + length, y);
        ctx.stroke();
    }

    // 1. Draw fixed point O
    ctx.font = "24px Times New Roman";
    ctx.fillText('O', baseX - 30, baseY + 8);
    ctx.beginPath();
    ctx.arc(baseX, baseY, 5, 0, 2 * Math.PI);
    ctx.fill();

    // 2. Draw the spring and its label 'k'
    drawSpring(ctx, baseX, baseY, springLength, 12, 12);
    ctx.font = "italic 24px Times New Roman";
    ctx.fillText('k', baseX + springLength / 2 - 5, baseY - 30);

    // 3. Draw the mass 'm'
    ctx.beginPath();
    ctx.arc(massX, massY, massRadius, 0, 2 * Math.PI);
    ctx.fill();
    ctx.fillText('m', massX - 35, massY - 15);

    // 4. Draw the velocity vector 'v₀'
    const vecEndX = massX + velocityVectorLength * Math.cos(angleRad);
    const vecEndY = massY + velocityVectorLength * Math.sin(angleRad);
    drawArrow(ctx, massX, massY, vecEndX, vecEndY);
    
    // Label for v₀
    ctx.font = "italic 24px Times New Roman";
    ctx.fillText('v', vecEndX + 8, vecEndY + 5);
    ctx.font = "italic 16px Times New Roman";
    ctx.fillText('0', vecEndX + 20, vecEndY + 10);


    // 5. Draw the 45° angle indication
    // Dashed reference line
    ctx.save();
    ctx.setLineDash([4, 4]);
    ctx.lineWidth = 1.5;
    ctx.beginPath();
    ctx.moveTo(massX, massY);
    ctx.lineTo(massX + 60, massY);
    ctx.stroke();
    ctx.restore();

    // Angle arc
    ctx.beginPath();
    ctx.lineWidth = 1.5;
    ctx.arc(massX, massY, 40, 0, angleRad, true);
    ctx.stroke();

    // Angle text
    ctx.font = "22px Times New Roman";
    ctx.fillText('45°', massX + 45, massY - 20);

    // 6. Draw the dimension line for 'l₀'
    const dimY = baseY + 70;
    const tickHeight = 15;
    const midX = baseX + springLength / 2;
    const labelGap = 30;
    const headLen = 10;

    // Ticks
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(baseX, dimY - tickHeight / 2); ctx.lineTo(baseX, dimY + tickHeight / 2);
    ctx.moveTo(massX, dimY - tickHeight / 2); ctx.lineTo(massX, dimY + tickHeight / 2);
    ctx.stroke();

    // Left arrow line
    ctx.beginPath();
    ctx.moveTo(midX - labelGap / 2, dimY);
    ctx.lineTo(baseX, dimY);
    ctx.stroke();
    // Left arrowhead (filled triangle)
    ctx.beginPath();
    ctx.moveTo(baseX, dimY);
    ctx.lineTo(baseX + headLen, dimY - headLen / 2);
    ctx.lineTo(baseX + headLen, dimY + headLen / 2);
    ctx.closePath();
    ctx.fill();

    // Right arrow line
    ctx.beginPath();
    ctx.moveTo(midX + labelGap / 2, dimY);
    ctx.lineTo(massX, dimY);
    ctx.stroke();
    // Right arrowhead (filled triangle)
    ctx.beginPath();
    ctx.moveTo(massX, dimY);
    ctx.lineTo(massX - headLen, dimY - headLen / 2);
    ctx.lineTo(massX - headLen, dimY + headLen / 2);
    ctx.closePath();
    ctx.fill();

    // Label for l₀
    ctx.font = "italic 24px Times New Roman";
    ctx.fillText('l', midX - 10, dimY + 8);
    ctx.font = "italic 16px Times New Roman";
    ctx.fillText('0', midX, dimY + 12);

  </script>
</body>
</html>